home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / grafik / viewer / amipeg06 / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-16  |  11.8 KB  |  543 lines

  1. /*
  2.  *  This is the main part
  3.  */
  4.  
  5. #include <intuition/screens.h>
  6. #include <proto/dos.h>
  7. #include <proto/exec.h>
  8.  
  9. #include "video.h"
  10. #include "proto.h"
  11. #include <sys/types.h>
  12. #include <signal.h>
  13.  
  14. #include <proto/timer.h>
  15. #include <devices/timer.h>
  16.  
  17. #include "util.h"
  18.  
  19. #define HELP_TEXT "NOB\t- ignore and not display any B frames.\n\
  20. NOP\t- ignore and not display any P frames.\n\
  21. LOOP\t- makes the player loop back to the beginning after reaching the end.\n\
  22. EACHSTAT- causes statistics to be displayed after each frame.\n\
  23. \t  Only valid when compiled with -DANALYSIS\n\
  24. NODISPLAY- dithers, but does not display, usually used for\n\
  25. \t  testing and timing purposes.\n\
  26. QUIET\t- supresses printing of frame numbers, timing information,\n\
  27. \t  and most error messages.\n\
  28. DITHER\t- selects from a variety of dither options.\n\
  29. \t  The possible values are:\n\
  30. \t\tcolor\n\
  31. \t\thiresham\n\
  32. \t\tham6\n\
  33. \t\tcybergfx\n\
  34. \t\tcybergfxgray\n\
  35. \t\tgray\n\
  36. \t\tnone\n\
  37. PUBSCREEN- open window on selected \"deep\" public screen. Only valid\n\
  38. \t  with DITHER cybergfx or cybergfxgray. Use with \"DEFAULT\" to open\n\
  39. \t  on current default public screen.\n\
  40. MODEID\t- select modeid for screen to open and play on.\n\
  41. FRAMERATE- speed in frames per second. (0 - as fast as possible).\n\
  42. BUFFER\t- size of the io buffer (default - 65536).\n\
  43. FILE\t- filename of MPEG stream.\n"
  44.  
  45. #define TEMPLATE "NOB/S,NOP/S,LOOP/S,EACHSTAT/S,ND=NODISPLAY/S,QUIET/S,DITHER/K,PS=PUBSCREEN/K,MODEID/K,FRAMERATE=FPS/K,BUFFER=BUF/K,FILE/A"
  46.  
  47. #define OPT_NOB                0
  48. #define OPT_NOP                1
  49. #define OPT_LOOP            2
  50. #define OPT_EACHSTAT    3
  51. #define OPT_NODISPLAY    4
  52. #define OPT_QUIET            5
  53. #define OPT_DITHER        6
  54. #define    OPT_PUBSCREEN    7
  55. #define OPT_MODEID        8
  56. #define OPT_FPS                9
  57. #define OPT_BUFFER        10
  58. #define OPT_FILE            11
  59. #define OPT_COUNT            12
  60.  
  61.  
  62. const char *dither_names = "ham6\1color\1hiresham\1ham6\1cybergfx\1cybergfxgray\1gray\1none";
  63. /*                          01234 56789  1113151719 2123 2527293133 353739414345 474951 53
  64.    got it? :)                          10 12141618 202224 26283032 34363840424446 4850 525456
  65. */
  66.  
  67. char animname[1024];
  68. char pubscreen_name[MAXPUBSCREENNAME + 1];
  69. char *pubname_ptr;
  70.  
  71. /* Declaration of global variable to hold dither info. */
  72.  
  73. int ditherType;
  74.  
  75. /* size of the io buffer */
  76.  
  77. int buf_length = 65536;
  78.  
  79. /* Global file pointer to incoming data. */
  80. FILE *input;
  81.  
  82. /* End of File flag. */
  83. static int EOF_flag = 0;
  84.  
  85. /* Loop flag. */
  86. int loopFlag = 0;
  87.  
  88. /* Quiet flag. */
  89. int quietFlag = 0;
  90.  
  91. /* Display image on screen? */
  92. int noDisplayFlag = 0;
  93.  
  94. /* Setjmp/Longjmp env. */
  95. jmp_buf env;
  96.  
  97. /* HAM6 rendering / HAM hires flag */
  98. extern int ham6, lores;
  99.  
  100. /* modeid of CyberGraphX screen */
  101. unsigned long modeid = 0xffffffff;
  102.  
  103. /* are we going to play on the Public Screen? */
  104. int cyber_pub = 0;
  105.  
  106. /* Framerate, -1: specified in stream (default)
  107.                0: as fast as possible
  108.                N (N>0): N frames/sec  
  109.                */
  110. int framerate = -1;
  111.  
  112. /* these are for timer.device */
  113. struct Library *TimerBase;
  114. struct MsgPort *TimerMP;           /* Message port pointer */
  115. struct timerequest *TimerIO;  /* I/O structure pointer */
  116.  
  117. /* Method of picture conversion */
  118. void (*DoDitherImage)(unsigned char *l, unsigned char *Cr, unsigned char *Cb,
  119.               unsigned char *disp, int h, int w);
  120.  
  121. static char version[]="$VER: aMiPEG 0.6 (compiled on " __DATE__ ", " __TIME__ ")\n";
  122.  
  123. /*
  124.  *--------------------------------------------------------------
  125.  *
  126.  * get_more_data --
  127.  *
  128.  *    Called by correct_underflow in bit parsing utilities to
  129.  *      read in more data.
  130.  *
  131.  * Results:
  132.  *    Input buffer updated, buffer length updated.
  133.  *      Returns 1 if data read, 0 if EOF, -1 if error.
  134.  *
  135.  * Side effects:
  136.  *      None.
  137.  *
  138.  *--------------------------------------------------------------
  139.  */
  140.  
  141. int get_more_data(unsigned int *buf_start, int max_length, int *length_ptr, unsigned int **buf_ptr)
  142. {
  143.   
  144.   int length, num_read, request;
  145.   unsigned char *buffer, *mark;
  146.  
  147.   if (EOF_flag) return 0;
  148.  
  149.   length = *length_ptr;
  150.   buffer = (unsigned char *) *buf_ptr;
  151.  
  152.   if (length > 0) {
  153.     memcpy((unsigned char *) buf_start, buffer, (length*4));
  154.     mark = ((unsigned char *) (buf_start + length));
  155.   }
  156.   else {
  157.     mark = (unsigned char *) buf_start;
  158.     length = 0;
  159.   }
  160.  
  161.   request = (max_length-length)*4;
  162.   
  163.   num_read = fread( mark, 1, request, input);
  164.  
  165.   /* Paulo Villegas - 26/1/1993: Correction for 4-byte alignment */
  166.   {
  167.     int num_read_rounded;
  168.     unsigned char *index;
  169.  
  170.     num_read_rounded = num_read & 0xfffffffc;
  171.  
  172.     /* this can happen only if num_read<request; i.e. end of file reached */
  173.     if( num_read_rounded < num_read )
  174.       { 
  175.      num_read_rounded+=4;
  176.      /* fill in with zeros */
  177.      for( index=mark+num_read; index<mark+num_read_rounded; *(index++)=0 );
  178.      /* advance to the next 4-byte boundary */
  179.      num_read = num_read_rounded;
  180.       }
  181.   }
  182.   
  183.   if (num_read < 0) {
  184.     return -1;
  185.   }
  186.   else if (num_read == 0) {
  187.     *buf_ptr = buf_start;
  188.     
  189.     /* Make 32 bits after end equal to 0 and 32
  190.        bits after that equal to seq end code
  191.        in order to prevent messy data from infinite
  192.        recursion.
  193.     */
  194.  
  195.     *(buf_start + length) = 0x0;
  196.     *(buf_start + length+1) = SEQ_END_CODE;
  197.  
  198.     EOF_flag = 1;
  199.     return 0;
  200.   }
  201.  
  202.   num_read >>= 2;
  203.  
  204.   *buf_ptr = buf_start;
  205.   *length_ptr = length + num_read;
  206.  
  207.   return 1;
  208. }
  209.  
  210. /*
  211.  *--------------------------------------------------------------
  212.  *
  213.  * int_handler --
  214.  *
  215.  *    Handles Cntl-C interupts..
  216.  *
  217.  * Results:
  218.  *    None.
  219.  *
  220.  * Side effects:
  221.  *    None.
  222.  *
  223.  *--------------------------------------------------------------
  224.  */
  225. void int_handler(int dummy)
  226. {
  227.     if (!quietFlag) fprintf(stderr, "Interrupted!\n");
  228.     if (curVidStream) DestroyVidStream(curVidStream);
  229.     exit(1);
  230. }
  231.  
  232.  
  233. /*
  234.  *--------------------------------------------------------------
  235.  *
  236.  * init_timer --
  237.  *
  238.  *    Prepare timer.device and IORequest for later use
  239.  *
  240.  * Results:
  241.  *    None.
  242.  *
  243.  * Side effects:
  244.  *    None.
  245.  *
  246.  *--------------------------------------------------------------
  247.  */
  248.  
  249. void init_timer(void)
  250. {
  251.     /* Create port for timer device communications */
  252.     if(TimerMP = CreatePort(NULL, 0))
  253.         /* Create message block for device IO */
  254.         if(TimerIO = (struct timerequest *)CreateExtIO(TimerMP, sizeof(struct timerequest)))
  255.  
  256.             /* Open the timer device with UNIT_MICROHZ */
  257.             if(!OpenDevice(TIMERNAME, UNIT_MICROHZ, (struct IORequest *)TimerIO, 0))
  258.             {
  259.                 TimerBase = (struct Library *)TimerIO->tr_node.io_Device;
  260.                 TimerIO->tr_node.io_Command = TR_ADDREQUEST;
  261.                 return;
  262.             }
  263.             else
  264.                 fprintf(stderr, "Error: Can't open Timer.device\n");
  265.         else
  266.             fprintf(stderr, "Error: Can't create IO request\n");
  267.     else
  268.         fprintf(stderr, "Error: Can't create port\n");
  269.  
  270.     exit(1);
  271. }
  272. /*
  273.  *--------------------------------------------------------------
  274.  *
  275.  * close_timer --
  276.  *
  277.  *    Close timer.device, remove IORequest and message port
  278.  *
  279.  * Results:
  280.  *    None.
  281.  *
  282.  * Side effects:
  283.  *    None.
  284.  *
  285.  *--------------------------------------------------------------
  286.  */
  287.  
  288. void close_timer(void)
  289. {
  290.     if(TimerBase)
  291.         CloseDevice((struct IORequest *)TimerIO);  /* Close Timer device */
  292.  
  293.     if(TimerIO)
  294.         DeleteExtIO((struct IORequest *)TimerIO);
  295.  
  296.     if(TimerMP)
  297.         DeletePort(TimerMP);
  298. }
  299.  
  300. /*
  301.  *--------------------------------------------------------------
  302.  *
  303.  * main --
  304.  *
  305.  *    Parses command line, starts decoding and displaying.
  306.  *
  307.  * Results:
  308.  *    None.
  309.  *
  310.  * Side effects:
  311.  *    None.
  312.  *
  313.  *--------------------------------------------------------------
  314.  */
  315.  
  316. void main(int argc, char **argv)
  317. {
  318.   static VidStream *theStream;
  319.   extern int lores;
  320.   LONG opts[OPT_COUNT];
  321.   struct RDArgs *rdargs;
  322.  
  323.   ditherType = FULL_COLOR_DITHER;
  324.   noDisplayFlag = 0;
  325.  
  326.     memset(opts, 0, sizeof(opts));
  327.  
  328.     if(rdargs = (struct RDArgs *)AllocDosObject(DOS_RDARGS, NULL))
  329.     {
  330.         rdargs->RDA_ExtHelp = HELP_TEXT;
  331.  
  332.         if(rdargs = ReadArgs(TEMPLATE, opts, rdargs))
  333.         {
  334.             if(opts[OPT_NOP])
  335.           TogglePFlag();
  336.  
  337.             if(opts[OPT_NOB])
  338.           ToggleBFlag();
  339.  
  340.             if(opts[OPT_DITHER])
  341.             {
  342.                 switch(strstr(dither_names, strlwr((char *)opts[OPT_DITHER])) - dither_names)
  343.                 {
  344.                     case 5:        /* color */
  345.                         ditherType = FULL_COLOR_DITHER;
  346.                         break;
  347.  
  348.                     case 11:    /* hiresham */
  349.                         ditherType = FULL_COLOR_DITHER;
  350.                         lores = FALSE;
  351.                         break;
  352.  
  353.                     case 0:    /* ham6 */
  354.                         ditherType = FULL_COLOR_DITHER;
  355.                         ham6 = TRUE;
  356.                         break;
  357.  
  358.                     case 25:    /* cybergfx */
  359.                         ditherType = CYBERGFX_DITHER;
  360.                         break;
  361.  
  362.                     case 34:    /* cybergfxgray */
  363.                         ditherType = CYBERGFXGRAY_DITHER;
  364.                         break;
  365.  
  366.                     case 42:    /* gray */
  367.                         ditherType = GRAY_DITHER;
  368.                         break;
  369.  
  370.                     case 52:    /* none */
  371.                         ditherType = NO_DITHER;
  372.                         break;
  373.  
  374.                     default:
  375.                         fprintf(stderr, "You should specify legal dither name after DITHER keyword.\n");
  376.                         FreeArgs(rdargs);
  377.                         exit(10);
  378.                 }
  379.             }
  380.  
  381.             if(opts[OPT_EACHSTAT])
  382. #ifdef ANALYSIS
  383.                 showEachFlag = 1;
  384. #else
  385.             {
  386.                 fprintf(stderr, "To use EACHSTAT, recompile with DEFINE ANALYSIS in CFLAGS\n");
  387.                 exit(1);
  388.             }
  389. #endif
  390.  
  391.             if(opts[OPT_QUIET])
  392.             quietFlag = 1;
  393.  
  394.             if(opts[OPT_LOOP])
  395.                 loopFlag = 1;
  396.  
  397.             if(opts[OPT_NODISPLAY])
  398.                 noDisplayFlag = 1;
  399.  
  400.             if(opts[OPT_PUBSCREEN])
  401.             {
  402.                 if(!stricmp("default", (char *)opts[OPT_PUBSCREEN]))
  403.                     pubname_ptr = NULL;
  404.                 else
  405.                 {
  406.                     strcpy(pubscreen_name, (char *)opts[OPT_PUBSCREEN]);
  407.                     pubname_ptr = pubscreen_name;
  408.                 }
  409.  
  410.                 cyber_pub = 1;
  411.             }
  412.  
  413.             if(opts[OPT_MODEID])
  414.                 if(sscanf((char *)opts[OPT_MODEID], "%x", &modeid) != 1)
  415.                 {
  416.                     fprintf(stderr, "ModeID should be an hexadecimal value.\n");
  417.                     FreeArgs(rdargs);
  418.                     exit(10);
  419.                 }
  420.  
  421.             if(opts[OPT_FPS])
  422.                 if(sscanf((char *)opts[OPT_FPS], "%d", &framerate) != 1)
  423.                 {
  424.                     fprintf(stderr, "You should specify a number after FRAMERATE keyword.\n");
  425.                     FreeArgs(rdargs);
  426.                     exit(10);
  427.                 }
  428.  
  429.             if(opts[OPT_BUFFER])
  430.                 if(sscanf((char *)opts[OPT_BUFFER], "%d", &buf_length) != 1)
  431.                 {
  432.                     fprintf(stderr, "You should specify a number after BUFFER keyword.\n");
  433.                     FreeArgs(rdargs);
  434.                     exit(10);
  435.                 }
  436.  
  437.             if(opts[OPT_FILE])
  438.             {
  439.                 input = fopen((char *)opts[OPT_FILE], "r");
  440.                 if(input == NULL)
  441.                 {
  442.                     fprintf(stderr, "Could not open file %s\n", (char *)opts[OPT_FILE]);
  443.                     FreeArgs(rdargs);
  444.                     exit(10);
  445.           }
  446.  
  447.                 strcpy(animname, (char *)opts[OPT_FILE]);
  448.  
  449.               signal(SIGINT, int_handler);
  450.  
  451.               init_tables();
  452.   
  453.               switch (ditherType)
  454.                 {
  455.                     case CYBERGFX_DITHER:
  456.                         InitColorDither();
  457.                         modeid = InitCyberGfxDisplay(modeid);
  458.                         HAM8_draw = (void (*)(void *, int, int)) DrawCyberGfxImage;
  459.                         DoDitherImage = ColorDitherImage_RGB;
  460.                         break;
  461.  
  462.                     case CYBERGFXGRAY_DITHER:
  463.                         InitColorDither();
  464.                         modeid = InitCyberGfxDisplay(modeid);
  465.                         HAM8_draw = (void (*)(void *, int, int)) DrawCyberGfxImage;
  466.                         DoDitherImage = NoDitherImage;
  467.                         break;
  468.  
  469.                     case GRAY_DITHER:
  470.                         InitColorDither();
  471.                         modeid = InitGrayDisplay(modeid);
  472.                         HAM8_draw = (void (*)(void *, int, int)) DrawGrayImage;
  473.                         DoDitherImage = NoDitherImage;
  474.                         break;
  475.  
  476.                     case FULL_COLOR_DITHER:
  477.                         InitColorDither();
  478.                         InitColorDisplay();
  479.                         break;
  480.  
  481.                     case NO_DITHER:
  482.                         HAM8_draw = (void (*)(void *, int, int)) NoDitherImage;    // method casting ... argh!
  483.                         DoDitherImage = NoDitherImage;
  484.                         break;
  485.                 }
  486.  
  487.                 init_timer();
  488.  
  489. /*
  490.  *  The new restart handling has not been checked out very closely with changing
  491.  *  (non)intra scale matrices!
  492.  */
  493.  
  494.                 theStream = NewVidStream(buf_length);
  495.  
  496.                 if (setjmp(env) != 0)
  497.                 {
  498.                     mpegInitVidRsrc(); /* fix bug in static first in mpegVidRsrc */
  499.  
  500.                     rewind(input);
  501.  
  502.                     EOF_flag = 0;
  503.                     theStream->bit_offset = 0;
  504.                     theStream->buf_length = 0;
  505.                     theStream->buffer = NULL;
  506.                     totNumFrames = 0;
  507. #ifdef ANALYSIS 
  508.                     init_stats();
  509. #endif
  510.                 }
  511.  
  512.                 realTimeStart = ReadSysClock();
  513.                 while (mpegVidRsrc(0, theStream));
  514.  
  515.             }
  516.  
  517.             FreeArgs(rdargs);
  518.         }
  519.         else
  520.         {
  521.             PrintFault(IoErr(), argv[0]);
  522.             exit(10);
  523.         }
  524.  
  525.         FreeDosObject(DOS_RDARGS, rdargs);
  526.     }
  527.     else
  528.     {
  529.         PrintFault(IoErr(), argv[0]);
  530.         exit(10);
  531.     }
  532. }
  533.     
  534.  
  535. /*
  536.  *  Dummy display method
  537.  *
  538.  */
  539. void NoDitherImage(unsigned char *l, unsigned char *Cr, unsigned char *Cb,
  540.            unsigned char *disp, int h, int w)
  541. {}
  542.  
  543.